from AIsearch.getInfor import Get_Map_Info, Get_Player_Info, Get_Enemy_Info
from AIsearch.Node import Node


# # 获取地图信息
# Get_Map_Info(CurrentMap, PlayerCon.floor)
#
# # 获取人物信息
#
# Get_Player_Info(Player)
# # 获取小怪信息
#
# Get_Enemy_Info(CurrentMap, id)
# id = Get_Map_Info(CurrentMap, PlayerCon.floor)[x][y]


# open_list 参与修改
# close_list 里面

class Player_way:
    def __init__(self, start_list, target_list, CurrentMap, Player):
        self.start_list = start_list
        self.target_list = target_list
        self.CurrentMap = CurrentMap
        self.open_list = {}
        self.close_list = {}
        self.Player = Player
        self.final_list = []
        self.f_list = []

    def add_in_open_list(self, node):  # 添加进入open_list
        self.open_list[(node.x, node.y)] = node

    def add_in_close_list(self, node):  # 添加进入close_list
        self.close_list[(node.x, node.y)] = node

    def update_open_list(self, node):  # 更新 openlist当中的值，确保其 一一对应
        self.open_list[(node.x, node.y)] = node

    def pop_min_in_open_list(self):  # 弹出openlist 当中的最小值
        key_min, node_min = None, None
        for key, node in self.open_list.items():
            if node_min is None:
                key_min, node_min = key, node
            elif node.f < node_min.f:
                key_min, node_min = key, node
        if key_min is not None:  # 弹出最小值并返回
            self.open_list.pop(key_min)
        return node_min

    def in_close_list(self, x, y):  # 判断该地图点是否在close_list 当中
        return self.close_list.get((x, y)) is not None

    def in_open_list(self, x, y):  # 判断该地图点是否在close_list 当中
        return self.open_list.get((x, y)) is not None

    def Get_near_list(self, node):
        Q = {}
        dir1 = [0, 0, 1, -1]
        dir2 = [1, -1, 0, 0]
        for i in range(4):
            My_id = Get_Map_Info(self.CurrentMap, self.Player.floor, [node.x + dir1[i], node.y + dir2[i]])
            if My_id != -1 and My_id != 2:  # 既不是非法也不是墙
                if 201 <= My_id <= 265:  # 是小鬼
                    Q[(node.x + dir1[i], node.y + dir2[i])] = Node(pos_list=[node.x + dir1[i], node.y + dir2[i]],
                                                                   child=[], parent=[],
                                                                   Type=Get_Enemy_Info(self.CurrentMap, My_id),
                                                                   target_list=self.target_list)
                else:  # 是空的
                    Q[(node.x + dir1[i], node.y + dir2[i])] = Node(pos_list=[node.x + dir1[i], node.y + dir2[i]],
                                                                   child=[], parent=[],
                                                                   Type=0, target_list=self.target_list)
        return Q

    def astar_search(self):  # A * 搜索的核心代码
        start = Node(pos_list=self.start_list, child=[], parent=[], Type=0, target_list=self.target_list)
        start.blood = self.Player.hp
        start.get_f()
        self.add_in_open_list(start)
        while True:
            E = self.pop_min_in_open_list()
            if E is None:
                print("Fail to find way to target")
                return -1
            if [E.x, E.y] is not self.target_list:
                self.add_in_close_list(E)

            Q = self.Get_near_list(E)
            if Q == {}:
                continue
            if Q.get((self.target_list[0], self.target_list[1])) is not None:
                self.answer = Node(pos_list=self.target_list, child=[], parent=[E], Type=0,
                                   target_list=self.target_list)
                self.answer.blood = E.blood - self.answer.Type
                if self.answer.blood <= 0:
                    print("Fail!Die from last step!")
                    Q.pop((self.target_list[0], self.target_list[1]))
                else:
                    print("Successfully plan!!")
                    return self.answer.blood
            for item in Q.items():
                if item[1].Type is 0:
                    tg = E.g + 1
                else:
                    tg = E.g + item[1].cost
                if self.in_close_list(item[1].x, item[1].y) and tg >= item[1].g:
                    continue
                elif self.in_open_list(item[1].x, item[1].y) and tg >= item[1].g:
                    continue
                else:
                    item[1].g = tg
                    item[1].blood = E.blood - item[1].Type
                    if item[1].blood <= 0:
                        item[1].g = 1000000
                        continue
                    item[1].get_f()
                    E.child.append(item[1])
                    item[1].parent.append(E)
                    self.add_in_open_list(item[1])

    def Getway_out(self):  # 获得控制率输出
        while len(self.answer.parent):
            # print((self.answer.x, self.answer.y),
            # 'G={0}, H={1}, F={2}'.format(self.answer.g, self.answer.h, self.answer.get_f()))
            if len(self.answer.parent):
                # print(self.answer.parent)
                self.f_list.append([self.answer.x, self.answer.y])
                delta = [self.answer.x - self.answer.parent[0].x, self.answer.y - self.answer.parent[0].y]
                if 201 <= Get_Map_Info(self.CurrentMap, self.Player.floor, [self.answer.x, self.answer.y]) <= 265:
                    Is_Mon = True
                else:
                    Is_Mon = False
                if delta[0] == 1:
                    self.final_list.append(3)
                elif delta[0] == -1:
                    self.final_list.append(4)
                elif delta[1] == 1:
                    self.final_list.append(2)
                elif delta[1] == -1:
                    self.final_list.append(1)
                if Is_Mon is True:
                    self.final_list.append(self.final_list[-1])
            else:
                break
            self.answer = self.answer.parent[0]
        self.final_list.reverse()
        print(self.f_list)
        print(self.final_list)
        return self.final_list  # 输出格式：  上下左右： final_list = [1,2,3,4]

